package com.fin.quant.app.ai;

import cn.hutool.core.util.NumberUtil;
import com.fin.quant.app.vo.*;
import com.fin.quant.common.MessageRole;
import com.fin.quant.domain.entity.AiConversationsEntity;
import com.fin.quant.domain.entity.AiMessagesEntity;
import com.fin.quant.domain.repository.ConversationRepository;
import com.fin.quant.domain.repository.MessageRepository;
import com.fin.quant.instra.rpc.AIServiceRpcClient;
import com.fin.quant.rpc.proto.AiService;
import com.google.common.collect.Lists;
import io.grpc.stub.StreamObserver;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.*;
import java.util.function.Consumer;
import java.util.stream.Collectors;

/**
 * AI gRPC客户端服务
 * 注意：这里先提供接口定义，实际的gRPC调用需要等proto文件编译生成Java类后实现
 */
@Service
@Slf4j
public class AIService {

    @Autowired
    private AIServiceRpcClient aiServiceRpcClient;

    @Autowired
    private ConversationRepository conversationRepository;

    @Autowired
    private MessageRepository messageRepository;


    private final ExecutorService executorService = Executors.newCachedThreadPool();


    /**
     * 调用AI聊天服务
     * TODO: 等proto文件编译后实现具体调用逻辑
     */
    public ChatResponseDto chat(ChatRequestDto chatRequestDto) {
        try {
            String message = chatRequestDto.getMessage();
            PageContext context = chatRequestDto.getContext();
            String conversationId = chatRequestDto.getConversationId();
            Long userId = StringUtils.isBlank(chatRequestDto.getUserId()) || !NumberUtil.isLong(chatRequestDto.getUserId()) ? 1L : Long.parseLong(chatRequestDto.getUserId());

            AiService.ChatRequest request = buildRequest(chatRequestDto);
            AiService.ChatResponse rpcChatResponse = aiServiceRpcClient.chat(request);

            // 添加 gRPC 响应日志
            log.info("AI gRPC response received - Success: {}, ConversationId: {}, Message: {}, Suggestions count: {}, Actions count: {}",
                    rpcChatResponse.getSuccess(),
                    rpcChatResponse.getConversationId(),
                    rpcChatResponse.getMessage(), // 只打印前100个字符
                    rpcChatResponse.getSuggestionsList().size(),
                    rpcChatResponse.getActionsList().size());

            if (!rpcChatResponse.getSuccess()) {
                return new ChatResponseDto(false, null, "AI服务暂时不可用");
            }

            // 保存对话记录到数据库
            conversationId = saveConversation(
                    rpcChatResponse.getConversationId(),
                    request.getUserId(),
                    context,
                    request.getMessage(),
                    rpcChatResponse.getMessage());

            // 构建响应
            List<String> suggestions = rpcChatResponse.getSuggestionsList();
            List<ActionButton> actions = rpcChatResponse.getActionsList().stream()
                    .map(this::convertToActionButton)
                    .collect(Collectors.toList());

            ChatData data = new ChatData(
                    rpcChatResponse.getMessage(),
                    conversationId,
                    suggestions,
                    actions);

            ChatResponseDto response = new ChatResponseDto(true, data, null);

            log.info("Calling AI service with message: {}", message);
            return response;
        } catch (Exception e) {
            log.error("AI gRPC call error:", e);
            throw new RuntimeException("AI服务调用异常", e);
        }
    }

    private AiService.ChatRequest buildRequest(ChatRequestDto chatRequestDto) {
        String message = chatRequestDto.getMessage();
        PageContext context = chatRequestDto.getContext();
        String conversationId = chatRequestDto.getConversationId();
        Long userId = StringUtils.isBlank(chatRequestDto.getUserId()) || !NumberUtil.isLong(chatRequestDto.getUserId()) ? 1L : Long.parseLong(chatRequestDto.getUserId());

        // TODO: 构建gRPC请求并调用Python AI服务
        AiService.PageContext.Builder contextBuilder =
                AiService.PageContext.newBuilder()
                        .setPageId(context.getPageId())
                        .setPageName(context.getPageName());

        if (context.getCurrentData() != null) {
            contextBuilder.setCurrentData(objectToJson(context.getCurrentData()));
        }

        if (context.getSelectedItems() != null) {
            contextBuilder.addAllSelectedItems(context.getSelectedItems());
        }

        List<AiService.MessageHistory> messageHistoryList = Lists.newArrayList();
        if (StringUtils.isNotBlank(conversationId)) {
            //历史对话
            List<AiMessagesEntity> historyMessages = messageRepository.findByConversationIdOrderByCreatedAtAsc(conversationId);
            if (CollectionUtils.isNotEmpty(historyMessages)) {
                AiService.MessageHistory.Builder historyBuilder = AiService.MessageHistory.newBuilder();
                for (AiMessagesEntity historyMessage : historyMessages) {
                    historyBuilder.setRole(historyMessage.getRole());
                    historyBuilder.setContent(historyMessage.getContent());
                    messageHistoryList.add(historyBuilder.build());
                }
            }
        }


        AiService.ChatRequest request = AiService.ChatRequest.newBuilder()
                .setMessage(message)
                .setContext(contextBuilder.build())
                .setConversationId(conversationId != null ? conversationId : "")
                .setUserId(userId)
                .addAllHistory(messageHistoryList)
                .build();
        return request;
    }

    public String saveConversation(String conversationId, Long userId,
                                   PageContext context, String userMessage, String aiResponse) {
        // 创建或更新对话
        AiConversationsEntity AiConversationsEntity;
        if (StringUtils.isNotBlank(conversationId)) {
            AiConversationsEntity = conversationRepository.findByConversationId(conversationId)
                    .orElse(createNewConversation(userId, context));
        } else {
            AiConversationsEntity = createNewConversation(userId, context);
        }

        AiConversationsEntity.setUpdatedAt(new Date());
        conversationRepository.saveOrUpdate(AiConversationsEntity);

        // 保存用户消息
        AiMessagesEntity userMsg = new AiMessagesEntity();
        userMsg.setMessageId(UUID.randomUUID().toString());
        userMsg.setConversationId(AiConversationsEntity.getConversationId());
        userMsg.setRole(MessageRole.USER.getValue());
        userMsg.setContent(userMessage);
        if (context != null) {
            userMsg.setContext(objectToJson(context));
        }
        messageRepository.saveOrUpdate(userMsg);

        // 保存AI回复
        AiMessagesEntity aiMsg = new AiMessagesEntity();
        aiMsg.setMessageId(UUID.randomUUID().toString());
        aiMsg.setConversationId(AiConversationsEntity.getConversationId());
        aiMsg.setRole(MessageRole.ASSISTANT.getValue());
        aiMsg.setContent(aiResponse);
        messageRepository.saveOrUpdate(aiMsg);

        return AiConversationsEntity.getConversationId();
    }


    /**
     * 创建新对话
     */
    private AiConversationsEntity createNewConversation(Long userId, PageContext context) {
        AiConversationsEntity AiConversationsEntity = new AiConversationsEntity();
        AiConversationsEntity.setConversationId(UUID.randomUUID().toString());
        AiConversationsEntity.setUserId(userId);
        if (context != null) {
            AiConversationsEntity.setPageId(context.getPageId());
        }
        return AiConversationsEntity;
    }

    /**
     * 转换ActionButton
     */
    private ActionButton convertToActionButton(Object actionObj) {
        // TODO: 实现具体的转换逻辑
        return new ActionButton("示例操作", "example_action", null);
    }


    /**
     * 对象转JSON字符串
     */
    private String objectToJson(Object obj) {
        try {
            com.fasterxml.jackson.databind.ObjectMapper mapper = new com.fasterxml.jackson.databind.ObjectMapper();
            return mapper.writeValueAsString(obj);
        } catch (Exception e) {
            log.error("Object to JSON conversion failed", e);
            return "{}";
        }
    }

    /**
     * 聊天流
     */
    public SseEmitter chatStream(ChatRequestDto requestDto) {
        SseEmitter emitter = new SseEmitter(30000L); // 30秒超时

        // 异步处理流式响应
        CompletableFuture.runAsync(() -> {
            try {
                // 发起流式调用
                chatStream(requestDto, emitter);

                // 发送完成信号
                emitter.send(SseEmitter.event()
                        .name("complete")
                        .data("stream_completed"));
                emitter.complete();

            } catch (Exception e) {
                emitter.completeWithError(e);
            }
        }, executorService);

        return emitter;
    }

    public static CommandActionDto fromCommandAction(AiService.CommandAction commandAction) {
        CommandActionDto dto = new CommandActionDto();
        dto.setActionType(commandAction.getActionType());
        dto.setCommand(commandAction.getCommand());
        dto.setParams(commandAction.getParams());
        dto.setDescription(commandAction.getDescription());
        dto.setPriority(commandAction.getPriority());
        return dto;
    }

    public static StatusUpdateDto fromStatusUpdate(AiService.StatusUpdate statusUpdate) {
        StatusUpdateDto dto = new StatusUpdateDto();
        dto.setStatus(statusUpdate.getStatus());
        dto.setMessage(statusUpdate.getMessage());
        dto.setProgress(statusUpdate.getProgress());
        return dto;
    }

    public static ErrorInfoDto fromErrorInfo(AiService.ErrorInfo errorInfo) {
        ErrorInfoDto dto = new ErrorInfoDto();
        dto.setErrorCode(errorInfo.getErrorCode());
        dto.setErrorMessage(errorInfo.getErrorMessage());
        dto.setDetails(errorInfo.getDetails());
        return dto;
    }

    /**
     * 流式聊天调用
     *
     * @param requestDto 聊天请求
     */
    private void chatStream(ChatRequestDto requestDto, SseEmitter emitter) {

        CountDownLatch finishLatch = new CountDownLatch(1);

        // 定义回调函数
        Consumer<String> onTextContent = text -> {
            try {
                // 发送文本内容到前端
                emitter.send(SseEmitter.event()
                        .name("text")
                        .data(text));
            } catch (IOException e) {
                emitter.completeWithError(e);
            }
        };

        Consumer<AiService.CommandAction> onCommandAction = command -> {
            try {
                // 发送命令到前端
                emitter.send(SseEmitter.event()
                        .name("command")
                        .data(fromCommandAction(command)));
            } catch (IOException e) {
                emitter.completeWithError(e);
            }
        };

        Consumer<AiService.StatusUpdate> onStatusUpdate = status -> {
            try {
                // 发送状态更新到前端
                emitter.send(SseEmitter.event()
                        .name("status")
                        .data(fromStatusUpdate(status)));
            } catch (IOException e) {
                emitter.completeWithError(e);
            }
        };

        Consumer<AiService.ErrorInfo> onError = error -> {
            try {
                // 发送错误信息到前端
                emitter.send(SseEmitter.event()
                        .name("error")
                        .data(fromErrorInfo(error)));
            } catch (IOException e) {
                emitter.completeWithError(e);
            }
        };

        StreamObserver<AiService.ChatStreamResponse> responseObserver = new StreamObserver<AiService.ChatStreamResponse>() {
            @Override
            public void onNext(AiService.ChatStreamResponse response) {
                try {
                    switch (response.getType()) {
                        case TEXT_CONTENT:
                            // 处理文本内容 - 用于显示
                            if (response.hasTextContent()) {
                                onTextContent.accept(response.getTextContent());
                            }
                            break;

                        case COMMAND_ACTION:
                            // 处理可执行命令
                            if (response.hasCommandAction()) {
                                AiService.CommandAction command = response.getCommandAction();
                                onCommandAction.accept(command);

                                // 根据命令类型执行相应操作
                                executeCommand(command);
                            }
                            break;

                        case STATUS_UPDATE:
                            // 处理状态更新
                            if (response.hasStatusUpdate()) {
                                AiService.StatusUpdate status = response.getStatusUpdate();
                                onStatusUpdate.accept(status);

                                // 更新UI状态
                                updateUIStatus(status);
                            }
                            break;

                        case ERROR_INFO:
                            // 处理错误信息
                            if (response.hasErrorInfo()) {
                                AiService.ErrorInfo error = response.getErrorInfo();
                                onError.accept(error);
                            }
                            break;

                        case FINAL_RESPONSE:
                            // 最终响应，可以在这里处理建议和操作按钮
                            System.out.println("收到最终响应，对话ID: " + response.getConversationId());
                            break;

                        default:
                            System.out.println("未知响应类型: " + response.getType());
                    }
                } catch (Exception e) {
                    System.err.println("处理响应时出错: " + e.getMessage());
                }
            }

            @Override
            public void onError(Throwable t) {
                System.err.println("流式调用出错: " + t.getMessage());
                finishLatch.countDown();
            }

            @Override
            public void onCompleted() {
                System.out.println("流式调用完成");
                finishLatch.countDown();
            }
        };

        // 发起流式调用
        AiService.ChatRequest request = buildRequest(requestDto);
        aiServiceRpcClient.chatStream(request, responseObserver);

        try {
            // 等待调用完成，最多等待30秒
            if (!finishLatch.await(30, TimeUnit.SECONDS)) {
                System.err.println("调用超时");
            }
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            System.err.println("调用被中断");
        }
    }

    /**
     * 执行命令动作
     */
    private void executeCommand(AiService.CommandAction command) {
        System.out.println("执行命令: " + command.getCommand());
        System.out.println("命令类型: " + command.getActionType());
        System.out.println("参数: " + command.getParams());
        System.out.println("描述: " + command.getDescription());

        // 根据命令类型执行相应操作
        switch (command.getActionType()) {
            case "navigate":
                handleNavigationCommand(command);
                break;
            case "execute":
                handleExecutionCommand(command);
                break;
            case "suggestion":
                handleSuggestionCommand(command);
                break;
            case "action":
                handleActionCommand(command);
                break;
            default:
                System.out.println("未知命令类型: " + command.getActionType());
        }
    }

    /**
     * 处理导航命令
     */
    private void handleNavigationCommand(AiService.CommandAction command) {
        switch (command.getCommand()) {
            case "add_to_portfolio":
                System.out.println("执行: 添加资产到投资组合");
                // 调用相应的业务逻辑
                break;
            case "view_details":
                System.out.println("执行: 查看详细信息");
                // 调用相应的业务逻辑
                break;
            default:
                System.out.println("未知导航命令: " + command.getCommand());
        }
    }

    /**
     * 处理执行命令
     */
    private void handleExecutionCommand(AiService.CommandAction command) {
        switch (command.getCommand()) {
            case "analyze":
                System.out.println("执行: 分析操作");
                // 调用相应的业务逻辑
                break;
            default:
                System.out.println("未知执行命令: " + command.getCommand());
        }
    }

    /**
     * 处理建议命令
     */
    private void handleSuggestionCommand(AiService.CommandAction command) {
        System.out.println("显示建议: " + command.getDescription());
        // 在UI中显示建议
    }

    /**
     * 处理操作命令
     */
    private void handleActionCommand(AiService.CommandAction command) {
        System.out.println("执行操作: " + command.getDescription());
        // 执行相应的操作
    }

    /**
     * 更新UI状态
     */
    private void updateUIStatus(AiService.StatusUpdate status) {
        System.out.println("状态更新: " + status.getStatus());
        System.out.println("消息: " + status.getMessage());
        if (status.hasProgress()) {
            System.out.println("进度: " + status.getProgress() + "%");
        }

        // 更新UI进度条和状态文本
        updateProgressBar(status.getProgress());
        updateStatusText(status.getMessage());
    }

    /**
     * 更新进度条（示例方法）
     */
    private void updateProgressBar(int progress) {
        // 在实际应用中，这里会更新UI组件的进度条
        System.out.println("更新进度条: " + progress + "%");
    }

    /**
     * 更新状态文本（示例方法）
     */
    private void updateStatusText(String message) {
        // 在实际应用中，这里会更新UI组件的状态文本
        System.out.println("更新状态文本: " + message);
    }
}
